package com.hengpeng.common.scheduling;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.tiling.scheduling.ScheduleIterator;
import org.tiling.scheduling.Scheduler;
import org.tiling.scheduling.SchedulerTask;

import com.hengpeng.common.scheduling.iterators.ComplexMinutelyIterator;
import com.hengpeng.common.scheduling.iterators.ComplexWeeklyIterator;
import com.hengpeng.common.scheduling.iterators.CompositeIterator;
import com.hengpeng.common.scheduling.iterators.DailyIterator;
import com.hengpeng.common.scheduling.iterators.MillonSecondIterator;

/**
 * <pre>
 * 委托投注任务调度对象类
 * </pre>
 * @author linriqing
 * @version 1.0, 2006-12-29
 */
public class LotterySchedule
{
	private static final Log logger = LogFactory.getLog(LotterySchedule.class);

	/**
	 * 所有业务逻辑的接口
	 */
	private Command command = null;

	private ScheduleConfig scheduling;

	/**
	 * 调度器,实现来自于Scheduler接口
	 */
	private final Scheduler scheduler = new Scheduler();

	private ScheduleIterator tempIterator;

	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	/**
	 * 构造函数
	 * @param config 任务调度配置对象
	 */
	public LotterySchedule(ScheduleConfig config)
	{
		this.scheduling = config;
	}

	/**
	 * <pre>
	 * 取消任务调度
	 * </pre>
	 */
	public void cancel()
	{
		scheduler.cancel();
	}

	/**
	 * @return 任务调度配置信息
	 */
	public ScheduleConfig getConfig()
	{
		return scheduling;
	}

	/**
	 * <pre>
	 * 这里运用了tiling的一个Schedule framework ，他是基于Timer的改良版本，屏蔽底层的Timer操作;
	 * start事件是主入口 schedule方法开始一个新的调度任务，必须实现TimerTask的run()方法，否则抛出异常;
	 * RestrictedDailyIterator(para1,para2,para3,int[])的参数意义是时，分，秒，及每个星期,此方法支持星期迭代循环;
	 * DailyIterator(para1,para2,para3)的意义跟上一个相同，只不过他只支持每天迭代循环，不支持星期迭代;
	 * MillonSecondIterator(int)的意义为每隔多少毫秒进行迭代一次.
	 * </pre>
	 */
	public void start()
	{
		ScheduleIterator iterator = LotterySchedule.getIterator(this.scheduling);
		this.tempIterator = LotterySchedule.getIterator(this.scheduling);
		if (iterator == null)
		{
			return;
		}

		this.scheduling.setNextRuntime(this.tempIterator.next().getTime());

		scheduler.schedule(new SchedulerTask()
		{
			public void run()
			{
				try
				{
					command = (Command) Class.forName(scheduling.getClassImpl()).newInstance();
					scheduling.setLastRuntime(System.currentTimeMillis());
					long time = tempIterator.next().getTime();
					scheduling.setNextRuntime(time);
					command.excute(scheduling);
					scheduling.setLastRunState(true);
				}
				catch (InstantiationException e)
				{
					logger.error("任务调度的业务逻辑[" + scheduling.getClassImpl() + "]无法创建实例", e);
					scheduling.setLastErrMsg("调度时间[" + sdf.format(new Date()) + "],任务调度的业务逻辑["
							+ scheduling.getClassImpl() + "]无法创建实例");
					scheduling.setLastRunState(false);
				}
				catch (IllegalAccessException e)
				{
					logger.error("任务调度的业务逻辑[" + scheduling.getClassImpl() + "]时存在语法错误", e);

					scheduling.setLastErrMsg("调度时间[" + sdf.format(new Date()) + "],任务调度的业务逻辑["
							+ scheduling.getClassImpl() + "]时存在语法错误");
					scheduling.setLastRunState(false);
				}
				catch (ClassNotFoundException e)
				{
					logger.error("任务调度的业务逻辑[" + scheduling.getClassImpl() + "]不存在", e);

					scheduling.setLastErrMsg("调度时间[" + sdf.format(new Date()) + "],任务调度的业务逻辑["
							+ scheduling.getClassImpl() + "]不存在");
					scheduling.setLastRunState(false);
				}
				catch (Exception e)
				{
					logger.error("任务调度的业务逻辑异常", e);
					scheduling.setLastErrMsg("调度时间[" + sdf.format(new Date()) + "]," + e.getMessage());
					scheduling.setLastRunState(false);
				}

			}
		}, iterator);
	}

	/**
	 * <pre>
	 * 通过任务调度的配置信息获取任务调度的迭代器
	 * </pre>
	 * @param scheduleconfig 任务调度的配置信息
	 * @return 任务调度的迭代器
	 */
	public static ScheduleIterator getIterator(ScheduleConfig scheduleconfig)
	{
		CompositeIterator multiIterator = null;
		TimeIterator[] timeiterator = scheduleconfig.getIterator();
		List<ScheduleIterator> list = new ArrayList<ScheduleIterator>();
		for (int i = 0; i < timeiterator.length; i++)
		{
			ScheduleIterator iterator = null;
			TimeIterator iterator2 = timeiterator[i];
			String[] dayTimes = iterator2.getDaytimes();
			switch (iterator2.getRepeatMode())
			{
				// 任务不执行
				case -1:
					break;

				// 按千分之妙进行迭代
				case Calendar.MILLISECOND:
					iterator = new MillonSecondIterator(iterator2.getInterval());
					break;

				// 按分钟进行迭代
				case Calendar.MINUTE:
					iterator = new ComplexMinutelyIterator(iterator2.getInterval(), dayTimes);
					break;

				// 按天进行迭代
				case Calendar.DAY_OF_MONTH:
					iterator = new DailyIterator(iterator2.getInterval(), dayTimes);
					break;

				// 默认按星期进行迭代
				case Calendar.DAY_OF_WEEK:
				default:
					int[] weekDays = iterator2.getWeekdays();
					int[] realWeekDays = new int[weekDays.length];
					for (int j = 0; j < realWeekDays.length; j++)
					{
						realWeekDays[j] = weekDays[j] % 7 + 1;
					}
					iterator = new ComplexWeeklyIterator(dayTimes, realWeekDays);
					break;
			}
			if (iterator != null)
			{
				list.add(iterator);
			}
		}

		if (list.size() > 0)
		{
			ScheduleIterator[] iterators = new ScheduleIterator[list.size()];
			list.toArray(iterators);
			multiIterator = new CompositeIterator(iterators);
		}

		return multiIterator;
	}
}
